layui.define(["laydate", "laytpl", "table", "layer", "tableEdit", "form"], function(exports) {
	"use strict";
	var moduleName = 'tableTree'
		, _layui = layui
		, laytpl = _layui.laytpl
		, $ = _layui.$
		, table = _layui.table
		, layer = _layui.layer
		, tableEdit = _layui.tableEdit
		, editEntity = tableEdit.callbackFn('tableEdit(getEntity)')
		, form = _layui.form;
	//组件用到的css样式
	var thisCss = [];
	thisCss.push('.layui-tableEdit-checked i{background-color:#60b979!important;}');
	thisCss.push('.layui-tableEdit-edit{position:absolute;right:2px;font-size:18px;bottom:8px;z-index:8880;}');
	thisCss.push('.layui-tableEdit-edge{position:absolute;left:8px;bottom:0;font-size:15x;z-index:8881;}');
	thisCss.push('.layui-tableEdit-tab{position:absolute;left:25px;bottom:0;font-size:15px;z-index:8882;}');
	thisCss.push('.layui-tableEdit-span {position:absolute;left:25px;bottom:0;}');
	var thisStyle = document.createElement('style');
	thisStyle.innerHTML = thisCss.join('\n'), document.getElementsByTagName('head')[0].appendChild(thisStyle);

	var configs = {
		callbacks: {}
		, tableTreeCache: {}
		, isEmpty: function(data) {
			return typeof data === 'undefined' || data === null || data.length <= 0;
		}
		, parseConfig: function(cols, field) {
			var type, data, enabled, dateType, csField;
			cols.forEach(function(ite) {
				ite.forEach(function(item) {
					if (field !== item.field || !item.config) return;
					var config = item.config;
					type = config.type;
					data = config.data;
					enabled = config.enabled;
					dateType = config.dateType;
					csField = config.cascadeSelectField;
				});
			});
			return { type: type, data: data, enabled: enabled, dateType: dateType, cascadeSelectField: csField };
		}
	};


	var TableTree = function() { this.config = {} };
	TableTree.prototype = {
        /**
         * 表格树渲染
         * @param options 表格参数
         * @param isFirstRender 是否首次渲染
         */
		render: function(options, isFirstRender) {
			var that = this;
			if (isFirstRender) {
				that._done = options.done;
				$.extend(that.config, options);
				var treeConfig = that.config['treeConfig'];
				var done = function(result) {
					if (!result.data) result.data = table.cache[that.config.id] = [];
					configs.tableTreeCache[$(this.elem).attr('id')] = result.data;
					var params = { field: treeConfig.showField, element: this.elem };
					that.initTree(params);
					if (that._done) {
						that._done.call(this, result);
					}
				};
				that.config.done = done;
			} else {
				that.config = options;
			}
			that.tableEntity = table.render(that.config);
		}
        /**
         * 初始化表格树及为表格树注册相关事件
         * @param options
         */
		, initTree: function(options) {
			var data = configs.tableTreeCache[$(options.element).attr('id')];
			this.doInitTree(data, options.field, null, 0);
			this.closeAllTreeNodes();
			this.parseColsConfig();
			//先注销事件
			this.off();
			//注册事件
			this.events();
		}
        /**
         * 初始化表格树
         * @param arr 表格数据data
         * @param field 树状单元格字段
         * @param tr 初始化当前tr元素
         * @param lvl 当前行等级
         */
		, doInitTree: function(arr, field, tr, lvl) {
			var that = this;
			var tableBody = $(that.config.elem).next().find('div.layui-table-body');
			_layui.each(arr, function(key, item) {
				if (lvl === 0) {
					tr = tableBody.find('tr[data-index="' + key + '"]');
					$(tr).attr('tree-id', item[that.config.treeConfig.treeid]);
					var td = $(tr).find('td[data-field="' + field + '"]');
					var _div = td.find('div.layui-table-cell');
					var span = _div.find('span.layui-tableEdit-span');
					var text = item[that.config.treeConfig.showField]; text = configs.isEmpty(text) ? "" : text;
					!span[0] && (_div.text(''), _div.prepend('<div class="layui-tableTree-div"><span class="layui-tableEdit-span">' + text + '</span></div>'));
					if (!td.find('i.layui-tableEdit-edge')[0]) that.addIcon(tr, td, lvl, item);
				} else {
					tr = that.addTreeRow(tr, item, lvl);
				}
				if (item.treeList) {
					that.doInitTree(item.treeList, field, tr, lvl + 1)
				}
			});
		},
		parseColsConfig: function() {
			var that = this; that.config.colsConfig = {};
			that.config.cols.forEach(function(ite) {
				ite.forEach(function(item) {
					if (!item.config) return;
					that.config.colsConfig[item.field] = item.config;
				});
			});
		}
        /**
         *给当前tr新增子节点
         * @param tr 当前节点
         * @param data 子节点数据
         */
		, addTreeRow: function(tr, data, lvl) {
			var that = this;
			lvl = configs.isEmpty(lvl) ? 0 : parseInt(lvl);
			var treeid = that.config.treeConfig.treeid;
			if (configs.isEmpty(data[treeid])) {
				data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36);
			}
			var newTr = $('<tr data-lvl="' + (lvl + 1) + '" tree-id="' + data[treeid] + '"></tr>');
			tr.after(newTr);
			that.addElementToTr(data, tr, newTr, lvl + 1);
			return newTr;
		}
        /**
         * 根据当前treeid获取相关数据
         * @param arr 表格树数据
         * @param uniqueTreeid 当前treeid值
         * @returns {*}
         */
		, getDataByTreeId: function(arr, uniqueTreeid) {
			var treeid = this.config.treeConfig.treeid;
			for (var i = 0; i < arr.length; i++) {
				var item = arr[i];
				if (uniqueTreeid + "" === item[treeid] + "") {
					return item;
				} else {
					if (item.treeList && item.treeList.length > 0) {
						var data = this.getDataByTreeId(item.treeList, uniqueTreeid);
						if (data) return data;
					}
				}
			}
		}
        /**
         * 给当前行添加图标按钮
         * @param tr 当前tr
         * @param td 树状单元格
         * @param lvl 当前tr等级
         */
		, addIcon: function(tr, td, lvl, data) {
			var iconClass = configs.isEmpty(data.iconClass) ? 'layui-icon-triangle-r' : data.iconClass;
			var that = this
				, icon = $('<i class="layui-tree-icon-clk-helper layui-icon layui-tableEdit-edge ' + iconClass + '"></i>')
				, div = td.find('div.layui-tableTree-div')
				, _div = $('<div class="layui-tableTree-edit"></div>')
				, span = div.children('span.layui-tableEdit-span');
			if (lvl > 0) {
				var spanLeft = lvl * 21 + 25, iconLeft = lvl * 21 + 5;
				span.css('left', spanLeft + 'px');
				icon.css('left', iconLeft + 'px');
			}
			div.append(icon), $(td).append(_div);
			var add = $('<i class="layui-icon layui-icon-add-1 layui-tableEdit-edit"></i>'); _div.append(add);
			var update = $('<i class="layui-icon layui-icon-edit layui-tableEdit-edit"></i>'); _div.append(update)
			var remove = $('<i class="layui-icon layui-icon-delete layui-tableEdit-edit"></i>'); _div.append(remove);
			var sort = $('<i class="layui-icon layui-icon-return layui-tableEdit-edit asc" style="font-size: 16px"></i>'); _div.append(sort);
			_div.hide(); sort.css('transform', 'rotate(90deg)');
			var heightStyle = that.config.size;
			heightStyle = heightStyle ? heightStyle : '';
			if (heightStyle === 'sm') {  //兼容table的size类型
				span.css('bottom', '0px');
				icon.css('bottom', '0px');
				update.css('bottom', '4px');
				add.css('bottom', '4px');
				remove.css('bottom', '4px');
				sort.css('bottom', '4px');
			}
			if (heightStyle === 'lg') {
				span.css('bottom', '-1px');
				icon.css('bottom', '-1px');
				update.css('bottom', '15px');
				add.css('bottom', '15px');
				remove.css('bottom', '15px');
				sort.css('bottom', '15px');
			}
			sort.css('right', '3px'), remove.css('right', '24px'), update.css('right', '48px'), add.css('right', '72px');
		}
        /**
         * 事件注册
         */
		, events: function() {
			var that = this, filter = $(that.config.elem).attr('lay-filter')
				, tableBody = $(this.config.elem).next().find('div.layui-table-body')
				, tableTreeid = $(that.config.elem).attr('id')
				, iconClass = this.config.treeConfig.iconClass
				, showField = that.config.treeConfig.showField;

			//编辑图标事件注册
			tableBody.on('click', 'i.layui-tableEdit-edit', function(e) {
				//_layui.stope(e);
				var isAdd = $(this).hasClass('layui-icon-add-1')
					, isUpdate = $(this).hasClass('layui-icon-edit')
					, treeData = configs.tableTreeCache[tableTreeid]
					, isDelete = $(this).hasClass('layui-icon-delete')
					, isSort = $(this).hasClass('layui-icon-return');
				var tr = $(this).parents('tr');
				var td = $(this).parents('td'), field = td.data('field');
				var treeid = tr.attr('tree-id');
				var data = that.getDataByTreeId(treeData, treeid);
				var lvl = tr.data('lvl');
				lvl = lvl ? lvl : 0;
				if (isAdd) {//新增
					//回调tool(lay-filter)对应的方法 异步/同步获取数据后回调add方法进行新增行
					var thisObj = {
						value: null, data: data, field: field, add: function(newTree) {
							!newTree && (newTree = []);
							newTree = that.removeRepeatData(newTree);//treeid去重
							if (newTree.length <= 0) {
								var thisData = {};
								that.config.cols.forEach(function(item1) {
									item1.forEach(function(item) {
										if (item.field) {
											if (!(item.field in data)) {
												thisData[item.field] = null;
											}
										}
									});
								});
								newTree.push(thisData);
							}
							that.asyncAddTree(newTree, data, tr, lvl);
							var treeList = data.treeList;
							if (!treeList) treeList = data.treeList = [];
							var count = 0;
							while (count < newTree.length) {
								treeList.push(newTree[count]); count++;
							}
							that.openTreeNode(tr)
						}, event: 'add'
					};
					active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
				}

				//修改
				if (isUpdate) {
					var oldValue = that.parseTempletData(data, field);
					oldValue = oldValue ? oldValue : '';
					editEntity.input({
						element: td[0], oldValue: oldValue, callback: function(res) {
							var thisObj = {
								value: res, data: data, field: field, update: function(fields) {
									if (!fields) return;
									for (var key in fields) {
										data[key] = fields[key];
										var showValue = that.parseTempletData(data, key);
										showValue = showValue ? showValue : '';
										td.find('div.layui-table-cell span.layui-tableEdit-span').text(showValue)
									}
								}, event: 'edit'
							};
							active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
						}
					});
				}

				//删除
				if (isDelete) {
					layer.confirm('<div style="color: red;text-align: center;">确定删除吗？</div>', function(index) {
						var thisObj = {
							value: null, data: data, field: field, event: 'del', del: function() {
								var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
								//删除页面隐藏的树
								that.removeChildren(tr, lvl);
								//清楚缓存中的数据
								that.clearCacheData(data);
								tr.remove();
							}
						};
						active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
						layer.close(index);
					});
				}

				//排序 => 根据tree-id进行排序
				if (isSort) {
					var icon = $(this);
					var isAsc = icon.hasClass('asc');
					isAsc ? (icon.removeClass('asc'), icon.css('transform', 'rotate(-90deg)'), icon.addClass('desc'))
						: (icon.removeClass('desc'), icon.css('transform', 'rotate(90deg)'), icon.addClass('asc'));
					that.exeTreeNodesSort(tr, that.config.treeConfig.treeid, isAsc);
				}
			});

			table.on('checkbox(' + filter + ')', function(obj) {
				var thisInput = this
					, treeData = configs.tableTreeCache[tableTreeid];
				var tr = $(thisInput).parents('tr'), lvl = tr.data('lvl');
				lvl = lvl ? lvl : 0;
				obj.type === 'one' && function() {
					that.setChildNodeChecked(tr, lvl, obj.checked);
					that.setSupperNodeChecked(tr, obj.checked);
				}();
				var _treeid = tr.attr("tree-id");
				//注意
				//layui组件获取的obj.data可能不正确
				//所以在此直接以此方式获取 保证取到相对应节点数据
				obj.data = that.getDataByTreeId(treeData, _treeid);
				active.callbackFn.call(this, 'checkbox(' + filter + ')', obj);
			});

			//showField字段单元格点击事件，展开子叶节点
			var SPAN_SELECTOR = 'div.layui-tableTree-div span.layui-tableEdit-span';
			tableBody.on('click', SPAN_SELECTOR, function(e) {
				_layui.stope(e);
				var thisTreeElem = $(this).parents('tr');
				var lvl = thisTreeElem.data('lvl'); lvl = lvl ? lvl : 0;
				var icon = $(this).parents('td').find('i.layui-tableEdit-edge');
				var isShow = icon.hasClass('layui-tableEdit-clicked');
				//关闭或者展开子元素
				that.showOrHideChildrenNodes(thisTreeElem, lvl, !isShow);
				//选择三角图标

				if (icon.hasClass("layui-icon-triangle-r")) {
					that.rotateFunc(icon, !isShow);
				}
			});

			var ICON_SELECTOR = 'div.layui-tableTree-div i.layui-tree-icon-clk-helper';
			tableBody.on('click', ICON_SELECTOR, function(e) {
				_layui.stope(e);
				var thisTreeElem = $(this).parents('tr');
				var lvl = thisTreeElem.data('lvl'); lvl = lvl ? lvl : 0;
				var icon = $(this).parents('td').find('i.layui-tableEdit-edge');
				var isShow = icon.hasClass('layui-tableEdit-clicked');
				//关闭或者展开子元素
				that.showOrHideChildrenNodes(thisTreeElem, lvl, !isShow);
				//选择三角图标

				if (icon.hasClass("layui-icon-triangle-r")) {
					that.rotateFunc(icon, !isShow);
				}
			});

			//展示工具栏
			if (this.config.treeConfig.showToolbar) {
				//操作栏鼠标经过事件
				tableBody.on("mouseenter ", 'td[data-field="' + showField + '"]', function(e) {
					_layui.stope(e)
					tableBody.find('div.layui-tableTree-edit').hide();
					$(this).find('div.layui-tableTree-edit').show();
				});
				tableBody.on("mouseleave", 'td[data-field="' + showField + '"]', function(e) {
					_layui.stope(e)
					tableBody.find('div.layui-tableTree-edit').hide();
				});
			}

			var INPUT_SELECTOR = 'td[data-field="' + showField + '"] input.layui-tableEdit-input';
			tableBody.on('blur', INPUT_SELECTOR, function() {
				$(this).remove();
			});

			var toolEvent = 'tool(' + filter + ')';
			table.on(toolEvent, function(obj) {
				var zthis = this
					, field = $(zthis).data('field')
					, config = that.config.colsConfig[field]
					, treeData = configs.tableTreeCache[tableTreeid];
				obj.field = field;
				if (!config) {
					active.callbackFn.call(zthis, toolEvent, obj); return;
				}
				var callbackFn = function(res) {
					obj.value = Array.isArray(res) ? (res.length > 0 ? res : [{ name: '', value: '' }]) : res;
					active.callbackFn.call(zthis, toolEvent, obj);
				};
				var _treeid = $(zthis.parentNode).attr("tree-id");
				//子节点或表格树删除最上级节点后，layui组件得到的数据就不对了。
				//因此直接用getDataByTreeId函数获取
				obj.data = that.getDataByTreeId(treeData, _treeid);
				obj.update = function(fields) {
					if (!fields) return;
					for (var key in fields) {
						obj.data[key] = fields[key];
						var showValue = that.parseTempletData(obj.data, key);
						showValue = showValue ? showValue : '';
						$(zthis).find('div.layui-table-cell').text(showValue)
					}
				};
				if (config.type === 'select') {
					editEntity.register({ data: config.data, element: zthis, enabled: config.enabled, selectedData: obj.data[field], callback: callbackFn });
				} else if (config.type === 'date') {
					editEntity.date({ dateType: config.dateType, element: zthis, callback: callbackFn });
				} else if (config.type === 'input') {
					editEntity.input({ element: zthis, oldValue: obj.data[field], callback: callbackFn });
				} else if (config.type === 'signedInput') {
					editEntity.signedInput({ element: zthis, oldValue: obj.data[field], callback: callbackFn });
				} else active.callbackFn.call(zthis, toolEvent, obj);
			});

			var SELECTOR = 'div.layui-tableTree-div i.' + iconClass;
			tableBody.on('click', SELECTOR, function(e) {
				_layui.stope(e);
				var tr = $(this).parents('tr')
					, treeData = configs.tableTreeCache[tableTreeid];
				var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
				var td = $(this).parents('td')
					, field = td.data('field')
					, treeid = tr.attr('tree-id')
					, data = that.getDataByTreeId(treeData, treeid)
					, thisObj = {
						value: null, data: data, field: field, async: function(asyncTree) {
							that.openTreeNode(tr);
							if (!asyncTree || asyncTree.length === 0) return;
							asyncTree = that.removeRepeatData(asyncTree);
							if (asyncTree.length === 0) return;
							that.asyncAddTree(asyncTree, data, tr, lvl);
							if (!data.treeList) data.treeList = [];
							var count = 0;
							while (count < asyncTree.length) {
								data.treeList.push(asyncTree[count]); count++;
							}
							//图标改回来
							that.openTreeNode(tr);
						}, event: 'async'
					};
				active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
			});
		}, off: function() {
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			tableBody.off('click', 'i.layui-tableEdit-edit');
			var SPAN_SELECTOR = 'div.layui-tableTree-div span.layui-tableEdit-span';
			tableBody.off('click', SPAN_SELECTOR);
			var showField = this.config.treeConfig.showField;
			tableBody.off("mouseleave", 'td[data-field="' + showField + '"]');
			var INPUT_SELECTOR = 'td[data-field="' + showField + '"] input.layui-tableEdit-input';
			tableBody.off('blur', INPUT_SELECTOR);
			var iconClass = this.config.treeConfig.iconClass;
			var SELECTOR = 'div.layui-tableTree-div i.' + iconClass;
			tableBody.off('click', SELECTOR);
		}
        /**
         * 过滤treeid重复的节点数据
         * @param data 被过滤的数据
         * @returns {Array}
         */
		, removeRepeatData: function(data) {
			var noRepeatData = [], that = this;
			data.forEach(function(e) {
				if (that.checkedRepeatData(e)) return;//treeid重复则直接过滤
				noRepeatData.push(e);
			});
			return noRepeatData;
		}
        /**
         * 根据obj数据给当前节点新增子叶节点
         * @param obj Array类型 子叶节点数据
         * @param data 当前节点数据
         * @param tr 当前节点tr
         * @param lvl 当前节点等级
         */
		, asyncAddTree: function(obj, data, tr, lvl) {
			var that = this;
			var _treeid_ = that.config.treeConfig.treeid;
			var treepid = that.config.treeConfig.treepid;
			!obj && (obj = []);
			obj.forEach(function(e) {
				e[treepid] = data[_treeid_];
				tr = that.addTreeRow(tr, e, lvl);
				if (e.treeList && e.treeList.length > 0) {
					that.asyncAddTree(e.treeList, e, tr, lvl + 1);
				}
			});
			var nextIcon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
			that.rotateFunc(nextIcon, true);
		}
        /**
         * 按table表格列模板(templet)解析数据
         * @param d 当前节点数据
         * @param field 列字段
         * @returns {*}
         */
		, parseTempletData: function(d, field) {
			var rs = null;
			this.config.cols.forEach(function(item1) {
				item1.forEach(function(item2) {
					if (item2.field === field) {
						var templet = item2.templet;
						if (templet) {
							if (typeof templet === 'string') {
								rs = laytpl($(templet).html()).render(d);
							} else {
								rs = templet(d, field);
							}
						} else {
							rs = d[field];
						}
					}
				});
			});
			return rs;
		}
        /**
         * 清除当前数据
         * @param data 当前数据
         */
		, clearCacheData: function(data) {
			if (!data) return
			var treeid = this.config.treeConfig.treeid;
			var tableTreeid = $(this.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			this.clearChildCacheData(treeData, data[treeid]);
		}
        /**
         * 清除当前数据的子叶节点数据
         * @param list 表格树数据
         * @param uniqueTreeid 当前节点treeid字段值
         */
		, clearChildCacheData: function(list, uniqueTreeid) {
			var treeid = this.config.treeConfig.treeid;
			for (var i = 0; i < list.length; i++) {
				var item = list[i];
				if ((uniqueTreeid + "") === (item[treeid] + "")) {
					list.splice(i, 1); break;
				} else {
					if (item.treeList && item.treeList.length > 0) {
						this.clearChildCacheData(item.treeList, uniqueTreeid)
					}
				}
			}
		}
        /**
         * 旋转三角图标
         * @param icon 当前三角图标
         * @param isOpen true为关闭 false打开
         */
		, rotateFunc: function(icon, isOpen) {
			if (!isOpen) {
				icon.css('transform', '');
				icon.removeClass('layui-tableEdit-clicked');
			} else {
				icon.css('transform', 'rotate(90deg)');
				icon.addClass('layui-tableEdit-clicked');
			}
		}
        /**
         * 展开或者关闭当前节点及其叶子节点
         * @param elemTree 当前节点tr
         * @param lvl 当前节点等级
         * @param isShow true打开 false关闭
         */
		, showOrHideChildrenNodes: function(elemTree, lvl, isShow) {
			var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
			nextlvl = nextlvl ? nextlvl : 0;
			if (nextTreeElem[0] && nextlvl > lvl) {
				if (isShow) {
					if ((nextlvl - lvl) === 1) {
						nextTreeElem.show();
						var nextIcon = nextTreeElem.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
						if (nextIcon.hasClass('layui-tableEdit-clicked')) {
							nextTreeElem.show();
							this.showTreeNodes(nextTreeElem, nextlvl);
						}
					}
				} else {
					nextTreeElem.hide();
				}
				this.showOrHideChildrenNodes(nextTreeElem, lvl, isShow);
			}
		}
        /**
         * 展开当前节点及其叶子节点
         * @param elemTree 当前节点tr
         * @param lvl 当前节点等级
         */
		, showTreeNodes: function(elemTree, lvl) {
			var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
			nextlvl = nextlvl ? nextlvl : 0;
			if (nextTreeElem[0] && nextlvl > lvl) {
				if ((nextlvl - lvl) === 1) {
					nextTreeElem.show();
					var nextIcon = nextTreeElem.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
					if (nextIcon.hasClass('layui-tableEdit-clicked')) {
						nextTreeElem.show();
						this.showTreeNodes(nextTreeElem, nextlvl);
					}
				}
				this.showTreeNodes(nextTreeElem, lvl);
			}
		}
        /**
         * 获取当前节点的父节点
         * @param elem 当前节点tr
         * @param lvl 当前节点等级
         * @returns {null|*|jQuery|*}
         */
		, getParentNode: function(elem, lvl) {
			if (lvl === 0) return null;
			var tr = $(elem)
				, prevElem = tr.prev()
				, prevLvl = prevElem.data('lvl');
			prevLvl = prevLvl ? prevLvl : 0;
			if (lvl - prevLvl === 1) return prevElem;
			return this.getParentNode(prevElem, lvl);
		}
        /**
         * 删除当前节点的叶子节点
         * @param elemTree 当前节点tr
         * @param lvl 当前节点等级
         */
		, removeChildren: function(elemTree, lvl) {
			var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
			nextlvl = nextlvl ? nextlvl : 0;
			if (nextTreeElem[0] && nextlvl > lvl) {
				nextTreeElem.remove();
				this.removeChildren(elemTree, lvl);
			}
		}
        /**
         * 判断当前节点数据的treeid是否重复
         * @param data 当前节点数据
         * @returns {boolean}
         */
		, checkedRepeatData: function(data) {
			var treeid = this.config.treeConfig.treeid;
			var tableTreeid = $(this.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var ckeckData = this.getDataByTreeId(treeData, data[treeid]);
			return ckeckData ? true : false;
		}
        /**
         * 	获取选中节点数据
         * @returns {*}
         */
		, getCheckedTreeNodeData: function() {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			var tableTreeid = $(that.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var checkedElem = tableBody.find('td.layui-table-col-special div.layui-form-checked');
			if(checkedElem == null || checkedElem == undefined){
				return null;
			}
			var dataSet = new Set();
			checkedElem.each(function() {
				var tr = $(this).parents('tr').eq(0);
				var treeid = tr.attr('tree-id');
				var data = that.getDataByTreeId(treeData, treeid);
				dataSet.add(data);
			});
			return Array.from(dataSet);
		}
		, getRadioCheckedTreeNodeData: function() {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			var tableTreeid = $(that.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var checkedElem = tableBody.find('td.layui-table-col-special div.layui-form-radioed');
			if(checkedElem == null || checkedElem == undefined){
				return null;
			}
			var dataSet = [];
			checkedElem.each(function() {
				var tr = $(this).parents('tr').eq(0);
				var treeid = tr.attr('tree-id');
				var data = that.getDataByTreeId(treeData, treeid);
				dataSet.push(data);
			});
			return dataSet.length > 0 ? dataSet[0] : null;
		}
        /**
         * 获取当前节点的最顶级节点
         * @param elem 当前节点
         * @returns {*}
         */
		, getTopNode: function(elem) {
			var lvl = elem.data('lvl')
				, prevTr = elem.prev();
			lvl = lvl ? lvl : 0;
			if (lvl === 0) return elem;
			return this.getTopNode(prevTr);
		}
        /**
         * 重载表格树
         * @param options
         */
		, reload: function(options) {
			if (options && options.done) {
				this._done = options.done;
			}
			this.render(this.config);
		}
        /**
         * 指定节点或节点id展开节点
         * @param params 节点或节点id
         */
		, openTreeNode: function(params) {
			var that = this;
			var treeid, tr;
			if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
				treeid = params;
				tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
			} else {
				tr = $(params);
			}
			tr.show();
			var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
			var lvl = tr.data('lvl');
			lvl = lvl ? lvl : 0;
			that.showOrHideChildrenNodes(tr, lvl, true);
			that.rotateFunc(icon, true);
			var parentNode = that.getParentNode(tr, lvl);
			while (parentNode && parentNode[0]) {
				parentNode.show();
				icon = parentNode.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
				lvl = parentNode.data('lvl');
				lvl = lvl ? lvl : 0;
				that.rotateFunc(icon, true);
				parentNode = that.getParentNode(parentNode, lvl);
			}
			var topNode = that.getTopNode(tr);
			that.showOrHideChildrenNodes(topNode, 0, true);
		}
        /**
         * 指定节点或节点id折叠节点
         * @param params 节点或节点id
         */
		, closeTreeNode: function(params) {
			var that = this;
			var treeid, tr;
			if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
				treeid = params;
				tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
			} else {
				tr = $(params);
			}
			var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
			var lvl = tr.data('lvl');
			lvl = lvl ? lvl : 0;
			that.showOrHideChildrenNodes(tr, lvl, false);
			that.rotateFunc(icon, false);
		}
        /**
         * 展开所有节点
         */
		, openAllTreeNodes: function() {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			tableBody.find('tr').each(function(e) {
				var tr = $(this);
				var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
				$(this).show();
				that.rotateFunc(icon, true);
			});
		}
        /**
         * 折叠所有节点
         */
		, closeAllTreeNodes: function() {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			tableBody.find('tr').each(function(e) {
				var tr = $(this);
				var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
				var lvl = tr.data('lvl');
				lvl = lvl ? lvl : 0;
				if (lvl > 0) $(this).hide();
				that.rotateFunc(icon, false);
			});
		}
        /**
         * 表格树节点逐级排序
         * @param options {field:'xxx',desc:true} field：排序字段 desc => true降序、false升序
         * @param treeData 表格树数据
         */
		, sort: function(options, treeData) {
			var that = this;
			treeData.sort(function(o1, o2) {
				var isNum = /(^[-+]?\d+$)|(^[-+]?\d+\.\d+$)/
					, v1 = o1[options.field]
					, v2 = o2[options.field];
				if (isNum.test(v1) && isNum.test(v2)) {
					v1 = parseFloat(v1);
					v2 = parseFloat(v2);
					if (v1 > v2) {
						return 1;
					} else if (v1 < v2) {
						return -1;
					} else {
						return 0;
					}
				} else {
					if (v1 && !v2) {
						return 1;
					} else if (!v1 && v2) {
						return -1;
					}
					(v1 + '').localeCompare(v2 + '', 'zh-CN')
				}
			});
			if (options.desc) {
				treeData.reverse();
			}
			treeData.forEach(function(e) {
				if (e.treeList && e.treeList.length > 0) {
					that.sort(options, e.treeList);
				}
			});
		}
        /**
         * 获取表格树参数配置
         * @returns {*}
         */
		, getTableTreeData: function() {
			var tableTreeid = $(this.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			return treeData;
		}
        /**
         * 增加最上级节点 => 单个节点
         * @param data object类型
         */
		, addTopTreeNode: function(data) {
			var that = this;
			var treeid = that.config.treeConfig.treeid;
			var treepid = that.config.treeConfig.treepid;
			var tableTreeid = $(that.config.elem).attr('id')
				, treeData = configs.tableTreeCache[tableTreeid];
			if (treeData.length <= 0) {
				if (!data) {
					data = {};
				}
				that.config.cols.forEach(function(item1) {
					item1.forEach(function(item) {
						if (item.field) {
							if (!(item.field in data)) {
								data[item.field] = null;
							}
						}
					});
				});
				delete data[treepid]; //最上级行不能有treepid
				var url = that.config.url;
				var hasUrl = !configs.isEmpty(url);
				hasUrl && delete that.config.url;
				if (!data[treeid]) {
					data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
				}
				treeData.push(data);
				that.config.data = treeData;
				that.render(that.config);
				if (hasUrl) {
					delete that.config.data;
					that.config.url = url;
				}
				return;
			}

			if (!data || (data && typeof data !== 'object')) {
				data = {};
				for (var key in treeData[0]) {
					data[key] = null;
				}
			}
			delete data[treepid]; //最上级行不能有treepid
			var tr = $(that.config.elem).next().find('div.layui-table-body tr').eq(0);
			if (configs.isEmpty(data[treeid]) || that.checkedRepeatData(data)) {
				data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
			}
			var newTr = $('<tr data-index="' + treeData.length + '" tree-id="' + data[treeid] + '"></tr>');
			tr.before(newTr);
			data['LAY_TABLE_INDEX'] = treeData.length;
			treeData.push(data);
			that.addElementToTr(data, tr, newTr, 0);
			that.rotateFunc(newTr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge'), true);
		}
        /**
         * 新增行tr
         * @param data 当前行数据
         * @param tr newTr的前一行的tr
         * @param newTr 新增行tr
         * @param lvl 新增行等级
         */
		, addElementToTr: function(data, tr, newTr, lvl) {
			var that = this;
			tr.children('td').each(function() {
				var field = $(this).data('field'), td = null;
				if (field + "" === '0') {
					td = $('<td data-field="0" data-key="1-0-0" class="layui-table-col-special"></td>');
					td.append(this.innerHTML);
				} else {
					var attrsStr = []
						, _divclass = $(this).children('div.layui-table-cell').attr("class")
						, attrs = this.attributes;
					for (var i = 0; i < attrs.length; i++) {
						attrsStr.push(attrs[i].nodeName + '="' + attrs[i].nodeValue + '"');
					}
					var text = that.parseTempletData(data, field); //按模板进行解析
					text = text ? text : '';
					if (field === that.config.treeConfig.showField) {
						td = $('<td ' + attrsStr.join(" ") + '><div class="' + _divclass + '"><div class="layui-tableTree-div"><span class="layui-tableEdit-span">' + text + '</span></div></div></td>');
						that.addIcon(newTr, td, lvl, data);
					} else {
						newTr.append('<td ' + attrsStr.join(" ") + '><div class="' + _divclass + '">' + text + '</div></td>');
					}
				}
				newTr.append(td);
			});
			form.render('checkbox');
			form.render('radio');
		}
        /**
         * 指定节点或节点id删除节点及其叶子节点
         * @param params
         */
		, delTreeNode: function(params) {
			if (!params) return;
			var that = this;
			var tableTreeid = $(that.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var treeid, tr;
			if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
				treeid = params;
				tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
			} else {
				tr = $(params);
				treeid = tr.attr("tree-id");
			}
			var data = that.getDataByTreeId(treeData, treeid);
			var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
			//删除页面隐藏的树
			that.removeChildren(tr, lvl);
			//清楚缓存中的数据
			that.clearCacheData(data);
			tr.remove();
		}
        /**
         * 判断当前节点的叶子节点是否有被选中的
         * @param elem 当前节点tr
         * @param lvl 当前节点等级
         * @returns {boolean|*}
         */
		, childNodeHasChecked: function(elem, lvl) {
			var nextTreeElem = elem.next(), nextlvl = nextTreeElem.data('lvl');
			nextlvl = nextlvl ? nextlvl : 0;
			if (nextTreeElem[0] && nextlvl > lvl) {
				var div = $(nextTreeElem).find('td.layui-table-col-special div.layui-form-checkbox');
				return div.hasClass('layui-form-checked') ? true : this.childNodeHasChecked(nextTreeElem, lvl);
			} else {
				return false;
			}
		}
        /**
         * 设置当前节点及其叶子节点为被选中状态
         * @param elem 当前节点
         * @param lvl 当前节点等级
         * @param isChecked true为选中 false为取消选中
         */
		, setChildNodeChecked: function(elem, lvl, isChecked) {
			var nextTreeElem = elem.next(), nextlvl = nextTreeElem.data('lvl');
			nextlvl = nextlvl ? nextlvl : 0;
			if (nextTreeElem[0] && nextlvl > lvl) {
				this.setCheckboxInfo(nextTreeElem, isChecked);
				this.setChildNodeChecked(nextTreeElem, lvl, isChecked);
			}
		}
        /**
         * 设置当前节点的祖辈节点为被选中状态
         * @param elem 当前节点
         * @param isChecked true为选中 false为取消选中
         */
		, setSupperNodeChecked: function(elem, isChecked) {
			var that = this;
			var thisTreeid = $(elem).attr("tree-id")
				, treepid = that.config.treeConfig.treepid
				, tableTreeid = $(that.config.elem).attr('id')
				, treeData = configs.tableTreeCache[tableTreeid]
				, data = that.getDataByTreeId(treeData, thisTreeid)
				, thisTreepid = data[treepid]
				, tableBody = $(that.config.elem).next().find('div.layui-table-body')
				, ptr = tableBody.find('tr[tree-id="' + thisTreepid + '"]');
			var lvl = ptr.data('lvl');
			lvl = lvl ? lvl : 0;
			if (!isChecked) {
				if (!that.childNodeHasChecked(ptr, lvl)) {
					that.setCheckboxInfo(ptr, isChecked);
				}
			} else {
				that.setCheckboxInfo(ptr, isChecked);
			}
			if (lvl === 0) return;
			that.setSupperNodeChecked(ptr, isChecked);
		}
        /**
         * 设置当前节点的选中状态
         * @param elem 当前节点
         * @param isChecked true为选中 false为取消选中
         */
		, setCheckboxInfo: function(elem, isChecked) {
			var div = elem.find('td.layui-table-col-special div.layui-form-checkbox')
				, input = elem.find('td.layui-table-col-special input[type="checkbox"]');
			isChecked ? (div.addClass('layui-form-checked'), input.prop('checked', true))
				: (div.removeClass('layui-form-checked'), input.prop('checked', false));
		}
        /**
         * 关键词检索相关节点
         * @param value 关键词参数
         */
		, keywordSearch: function(value) {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			var spans = tableBody.find('td[data-field="' + this.config.treeConfig.showField + '"] span.layui-tableEdit-span');
			var tableTreeid = $(that.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var treepid = that.config.treeConfig.treepid;
			that.clearSearch();//每次搜索前都清除标记 然后再进行标记
			tableBody.find("tr").each(function() {
				var tr = $(this);
				if (!tr.is(":hidden")) {
					tr.addClass("layui-tableTree-search");
				}
			});
			var showArr = new Set();
			spans.each(function() {
				var thisValue = this.innerText;
				var tr = $(this).parents('tr').eq(0);
				if (thisValue.indexOf(value) > -1) {
					tr.show();
					var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge')
					tr.hasClass('layui-tableTree-search')
						&& !icon.hasClass('layui-tableEdit-clicked')
						&& (that.rotateFunc(icon, true), icon.addClass('layui-tableTree-search'));
					var treeid = tr.attr('tree-id');
					showArr.add(treeid)
					var data = that.getDataByTreeId(treeData, treeid);
					var _treepid = data[treepid];
					var parentNode = tableBody.find('tr[tree-id="' + _treepid + '"]');
					while (parentNode[0]) {
						parentNode.show();
						treeid = parentNode.attr('tree-id');
						data = that.getDataByTreeId(treeData, treeid);
						if (data) {
							showArr.add(treeid);
							icon = parentNode.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge')
							parentNode.hasClass('layui-tableTree-search')
								&& !icon.hasClass('layui-tableEdit-clicked')
								&& (that.rotateFunc(icon, true), icon.addClass('layui-tableTree-search'));
						}
						_treepid = data[treepid];
						parentNode = tableBody.find('tr[tree-id="' + _treepid + '"]');
					}
				} else {
					var treeid = tr.attr('tree-id');
					!showArr.has(treeid) && tr.hide();
				}
			});
		}
        /**
         * 重置表格树到检索前折叠状态
         */
		, clearSearch: function() {
			var that = this;
			var tableBody = $(this.config.elem).next().find('div.layui-table-body');
			var searchTrs = tableBody.find("tr.layui-tableTree-search");
			if (searchTrs.length <= 0) return;
			tableBody.find("tr").each(function() {
				var tr = $(this);
				if (tr.hasClass("layui-tableTree-search")) {
					tr.show();
					var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge.layui-tableTree-search');
					if (icon[0]) {
						that.rotateFunc(icon, false);
						icon.removeClass('layui-tableTree-search');
						icon.removeClass('layui-tableEdit-clicked');
					}
				} else {
					tr.hide();
				}
				tr.removeClass("layui-tableTree-search");
			});
		}
        /**
         * 刷新当前表格树 => 局部刷新
         * @param data 表格树数据
         * @param tr 当前节点tr
         * @param lvl 当前节点等级
         * @param isFirst 当前节点是否为表格树的第一个节点
         */
		, refreshTableBody: function(data, tr, lvl, isFirst) {
			var that = this;
			var treeid = that.config.treeConfig.treeid;
			var tbody = $(that.config.elem).next().find('div.layui-table-body tbody');
			_layui.each(data, function(index, item) {
				var newTr;
				if (!isFirst) tr = tbody.children(':last-child');
				newTr = lvl <= 0 ? $('<tr data-index="' + index + '" tree-id="' + item[treeid] + '"></tr>')
					: $('<tr data-lvl="' + lvl + '" tree-id="' + item[treeid] + '"></tr>');
				!isFirst ? tr.after(newTr) : (tbody.html(''), tbody.append(newTr));
				isFirst = false;
				that.addElementToTr(item, tr, newTr, lvl);
				if (item.treeList) {
					that.refreshTableBody(item.treeList, newTr, lvl + 1, false);
				}
			});
		}
        /**
         * 刷新当前表格树 => 局部刷新
         * @param data 表格树数据
         */
		, refresh: function(data) {
			var tableTreeid = $(this.config.elem).attr('id');
			var treeid = this.config.treeConfig.treeid;
			var treeData = configs.tableTreeCache[tableTreeid];
			if (data) {
				treeData.splice(0, treeData.length);
				data.forEach(function(e) {
					if (!e[treeid]) {
						e[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
					}
					treeData.push(e);
				})
			}
			this.sort({ field: this.config.treeConfig.treeid }, treeData);
			if (treeData.length < -0) return;
			_layui.each(treeData, function(index, item) {
				item['LAY_TABLE_INDEX'] = index;
			});
			var tr = $(this.config.elem).next().find('div.layui-table-body tr').eq(0);
			this.refreshTableBody(treeData, tr, 0, true);
			this.openAllTreeNodes();
			form.render('checkbox');
		}
        /**
         * 根据当前节点id获取叶子节点数据
         * @param treeData 表格树数据
         * @param treeid 当前节点id
         * @param childArr 获取的子节点数据
         */
		, findChildTreeNodes: function(treeData, treeid, childArr) {
			var that = this;
			var treepid = this.config.treeConfig.treepid;
			treeData.forEach(function(item) {
				if (treepid in item) {
					if (item[treepid] + "" === treeid + "") {
						childArr.push(item);
					} else {
						if (item.treeList) {
							that.findChildTreeNodes(item.treeList, treeid, childArr);
						}
					}
				} else {
					if (item.treeList) {
						that.findChildTreeNodes(item.treeList, treeid, childArr);
					}
				}
			});
		}
        /**
         * 指定节点/节点id逐级排序
         * @param params 节点/节点id
         * @param field 排序字段
         * @param isAsc true升序 false降序
         */
		, sortByTreeNode: function(params, field, isAsc) {
			if (!params) return;
			if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
				params = $(this.config.elem).next().find('div.layui-table-body tr[tree-id="' + params + '"]');
			}
			var tr = $(params); tr.show();
			this.exeTreeNodesSort(tr, field, isAsc);
			var lvl = tr.data('lvl'), icon; lvl = lvl ? lvl : 0;
			var parentNode = this.getParentNode(tr, lvl);
			while (parentNode && parentNode[0]) {
				parentNode.show();
				icon = parentNode.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
				lvl = parentNode.data('lvl');
				lvl = lvl ? lvl : 0;
				this.rotateFunc(icon, true);
				parentNode = this.getParentNode(parentNode, lvl);
			}
			var topNode = this.getTopNode(tr);
			this.showOrHideChildrenNodes(topNode, 0, true);
		}
        /**
         * 当前节点叶子节点逐级排序
         * @param tr 当前节点
         * @param field 排序字段
         * @param isAsc true升序 false降序
         */
		, exeTreeNodesSort: function(tr, field, isAsc) {
			var that = this;
			var tableTreeid = $(that.config.elem).attr('id');
			var treeData = configs.tableTreeCache[tableTreeid];
			var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
			var brotherArr = [];
			that.findChildTreeNodes(treeData, tr.attr('tree-id'), brotherArr);
			var $treeid = that.config.treeConfig.treeid;
			if (brotherArr.length > 0) {
				that.sort({ field: field, desc: isAsc }, brotherArr);
				brotherArr.forEach(function(item) {
					var ztr = $('tr[tree-id="' + item[$treeid] + '"]'), zlvl = ztr.data('lvl');
					zlvl = zlvl ? zlvl : 0;
					that.removeChildren(ztr, zlvl);
					ztr.remove();
				});
				var sortData = that.getDataByTreeId(treeData, tr.attr('tree-id'));
				that.asyncAddTree(brotherArr, sortData, tr, lvl);
			}
		}
	};

	var active = {
		on: function(event, callback) {
			var filter = event.match(/\((.*)\)$/), eventName = (filter ? (event.replace(filter[0], '') + '_' + filter[1]) : event);
			configs.callbacks[moduleName + '_' + eventName] = callback;
		},
		callbackFn: function(event, params) {
			var filter = event.match(/\((.*)\)$/), eventName = (filter ? (event.replace(filter[0], '') + '_' + filter[1]) : event);
			var key = moduleName + '_' + eventName, func = configs.callbacks[key];
			if (!func) return;
			return func.call(this, params);
		},
		render: function(options) {
			var tableTree = new TableTree();
			tableTree.render(options, true);
			return {
				getTreeOptions: function() {
					return tableTree.config;
				},
				getCheckedTreeNodeData: function() {
					return tableTree.getCheckedTreeNodeData();
				},
				getRadioCheckedTreeNodeData: function() {
					return tableTree.getRadioCheckedTreeNodeData();
				},
				reload: function(options) {
					tableTree.reload(options);
				},
				openTreeNode: function(params) {
					tableTree.openTreeNode(params);
				}
				, closeTreeNode: function(params) {
					tableTree.closeTreeNode(params);
				}
				, closeAllTreeNodes: function() {
					tableTree.closeAllTreeNodes();
				}
				, openAllTreeNodes: function() {
					tableTree.openAllTreeNodes();
				}
				, sort: function(options) {
					var tableTreeid = $(tableTree.config.elem).attr('id');
					var treeData = configs.tableTreeCache[tableTreeid];
					tableTree.sort(options, treeData);
					if (treeData.length < -0) return;
					_layui.each(treeData, function(index, item) {
						item['LAY_TABLE_INDEX'] = index;
					});
					var tr = $(tableTree.config.elem).next().find('div.layui-table-body tr').eq(0);
					tableTree.refreshTableBody(treeData, tr, 0, true);
					tableTree.openAllTreeNodes();
					form.render('checkbox');
				}
				, getTableTreeData: function() {
					return tableTree.getTableTreeData();
				}
				, addTopTreeNode: function(data) {
					tableTree.addTopTreeNode(data);
				}
				, delTreeNode: function(params) {
					tableTree.delTreeNode(params);
				}
				, keywordSearch: function(value) {
					tableTree.keywordSearch(value);
				}
				, clearSearch: function() {
					tableTree.clearSearch();
				}
				, refresh: function(data) {
					tableTree.refresh(data);
				}
				, sortByTreeNode: function(tr, field, isAsc) {
					tableTree.sortByTreeNode(tr, field, isAsc);
				}
			};
		}
	};
	exports(moduleName, active);
});